<?php

// +----------------------------------------------------------------------
// | 交易数据处理服务
// +----------------------------------------------------------------------
// | 主要服务于交易数据数据处理
// +----------------------------------------------------------------------
// | 错误编码头 231xxx
// +----------------------------------------------------------------------

namespace common\service;


use common\exception\LogicException;
use common\model\RechargeModel;
use common\model\TenantModel;
use support\ErrorCode;
use think\Exception;
use think\Request;

class TransactionService
{
    /**
     * 生成充值日志记录
     * @param $data
     * @param int $entryDirection
     * @return array
     */
    protected function generateRechargeLogParam($data, $entryDirection = 0)
    {
        $userUUID = \request()->getUserUUID();
        $param = [
            "type" => "recharge",
            "entry_direction" => $entryDirection,
            "amount" => (float)$data['amount'],
            "link_id" => (int)$data['id'],
            "created_by" => (string)$userUUID,
            "belong_system" => (string)C('BELONG_SYSTEM')
        ];

        return $param;
    }

    /**
     * 生成订单日志记录
     * @param $data
     * @param int $entryDirection
     * @return array
     */
    protected function generateOrderLogParam($data, $entryDirection = 0)
    {
        $userUUID = \request()->getUserUUID();
        $param = [
            "type" => "order",
            "entry_direction" => $entryDirection,
            "amount" => (float)$data['money'],
            "link_id" => (int)$data['id'],
            "created_by" => (string)$userUUID,
            "belong_system" => (string)$data['belong_system']
        ];

        return $param;
    }

    /**
     * 生成日志记录参数
     * @param $param
     */
    protected function writeLogParam($param)
    {
        $eventLogService = new EventLogService();
        $eventLogService->writeTransactionRecords($param);
    }

    /**
     * 通过银行转账充值
     * @param $data
     * @return array|bool
     * @throws Exception
     */
    public function rechargeByBankTransfer($data)
    {
        $addData = [
            'tenant_id' => $data['tenant_id'],
            'remittance_account' => $data['remittance_account'],
            'remittance_bank' => $data['remittance_bank'],
            'amount' => $data['amount']
        ];

        if (array_key_exists('remark', $data)) {
            $addData['remark'] = $data['remark'];
        }

        $rechargeModel = model(RechargeModel::class);

        // 执行新增操作
        $resData = $rechargeModel->addItem($addData);
        if (!$resData) {
            // 通用创建失败错误码 001
            throw_strack_exception($rechargeModel->getError(), ErrorCode::BANK_TRANSFER_RECHARGE_FAILED);
        } else {
            // 写入交易日志记录
            $this->writeLogParam($this->generateRechargeLogParam($resData));

            // 返回成功数据
            return $resData;
        }
    }

    /**
     * 检测当前用户操作充值表的合法性
     * @return bool
     */
    protected function checkRechargeOperateLegal()
    {
        // 获取平台租户id
        $optionsService = new OptionsService();
        $platformTenantSetting = $optionsService->getOptionsData('platform_tenant_settings');
        if (empty($platformTenantSetting) && empty($platformTenantSetting['tenant_id'])) {
            throw_strack_exception('The current user operation is illegal.', ErrorCode::ILLEGAL_OPERATION);
        }

        // 判断当前租户的合法性
        $userService = new UserService();
        if (!$userService->checkTenantIdInCurrentUser($platformTenantSetting['tenant_id'])) {
            throw_strack_exception('The current user operation is illegal.', ErrorCode::ILLEGAL_OPERATION);
        }
    }

    /**
     * 追加用户余额
     * @param $tenantId
     * @param $amount
     * @throws \Exception
     */
    protected function appendTenantAmount($tenantId, $amount)
    {
        $tenantModel = model(TenantModel::class);
        $balance = $this->getTenantBalance($tenantId);

        $tenantModel->startTrans();//强制开启事务
        try {
            $newBalance = (float)($balance + $amount);

            // 追加余额
            $tenantModel->where(['id' => $tenantId])->setField('balance', $newBalance);
            $tenantModel->commit();

        } catch (\Exception $e) {
            $tenantModel->rollback();
            throw_strack_exception($e->getMessage(), ErrorCode::FAILED_TO_ADD_USER_BALANCE);
        }
    }


    /**
     * 扣除用户余额
     * @param $tenantId
     * @param $amount
     * @throws \Exception
     */
    protected function deductTenantAmount($tenantId, $amount)
    {
        $tenantModel = model(TenantModel::class);
        $balance = $this->getTenantBalance($tenantId);

        $tenantModel->startTrans();//强制开启事务
        try {

            if ($amount > $balance) {
                throw new LogicException('Sorry, your credit is running low.', ErrorCode::YOUR_CREDIT_IS_RUNNING_LOW);
            }

            $newBalance = (float)($balance - $amount);

            // 扣除余额
            $tenantModel->where(['id' => $tenantId])->setField('balance', $newBalance);
            $tenantModel->commit();

        } catch (\Exception $e) {
            $tenantModel->rollback();
            throw_strack_exception($e->getMessage(), ErrorCode::FAILED_TO_DEDUCT_USER_BALANCE);
        }
    }

    /**
     * 确认充值
     * @param $rechargeId
     * @return bool
     * @throws \Exception
     */
    public function confirmRecharge($rechargeId)
    {
        // 判断当前租户操作的合法性
        $this->checkRechargeOperateLegal();

        $rechargeModel = model(RechargeModel::class);

        // 执行新增操作
        $resData = $rechargeModel->modifyItem([
            'id' => $rechargeId,
            'confirm' => 1
        ]);

        if (!$resData) {
            // 通用创建失败错误码 001
            throw_strack_exception($rechargeModel->getError(), ErrorCode::FAILED_TO_CONFIRM_RECHARGE);
        } else {

            // 给当前用户增加余额
            $rechargeData = $rechargeModel->field('tenant_id,amount')->where(['id' => $rechargeId])->find();

            $this->appendTenantAmount($rechargeData['tenant_id'], $rechargeData['amount']);

            // 写入交易日志记录
            $this->writeLogParam($this->generateRechargeLogParam($resData, 1));

            // 返回成功数据
            return $resData;
        }
    }

    /**
     * 查询指定租户的余额
     * @param $tenantId
     * @return float|int
     */
    public function getTenantBalance($tenantId)
    {
        $tenantModel = model(TenantModel::class);
        $balance = $tenantModel->where(['id' => $tenantId])->getField('balance');
        if (empty($balance)) {
            return 0;
        }
        return (float)$balance;
    }

    /**
     * 订单扣款
     * @param $orderData
     * @return array
     * @throws \Exception
     */
    public function orderDeduction($orderData)
    {
        $this->deductTenantAmount($orderData['tenant_id'], $orderData['money']);

        // 写入交易日志记录
        $this->writeLogParam($this->generateOrderLogParam($orderData));

        return [];
    }

    /**
     * 订单打款
     * @param $param
     * @return array
     */
    public function orderIncrease($param)
    {
        $this->increaseTenantAmount($param['tenant_id'], $param['money']);

        // 写入交易日志记录
        $this->writeLogParam($this->generateOrderLogParam($param, 1));

        return [];
    }

    /**
     * 增加租户余额
     * @param $tenantId
     * @param $money
     */
    private function increaseTenantAmount($tenantId, $money)
    {
        $tenantModel = model(TenantModel::class);

        $balance = $this->getTenantBalance($tenantId);

        $tenantModel->startTrans();//强制开启事务
        try {
            if ($money <= 0) {
                throw new LogicException("money should granter than 0", ErrorCode::MONEY_SHOULD_GRANTER_THAN_ZERO);
            }


            $newBalance = (float)($balance + $money);

            // 增加租户余额
            $tenantModel->where(['id' => $tenantId])->setField('balance', $newBalance);
            $tenantModel->commit();

        } catch (\Exception $e) {
            $tenantModel->rollback();
            throw_strack_exception($e->getMessage(), ErrorCode::FAILED_TO_INCREASE_TENANT_BALANCE);
        }
    }

    /**
     * 充值记录查询
     * @param $param
     * @param string $getModuleCode
     * @return array
     */
    public function selectRechargeList($param, string $getModuleCode)
    {
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $fields = $param['fields'] ?? "recharge.*";
        $order = $param['order'] ?? "recharge.id desc";
        $filter = $param['filter'] ?? [];
        $total = model(RechargeModel::class)
            ->join('tenant ON tenant.id = recharge.tenant_id')
            ->where($filter)
            ->count();
        $rows = model(RechargeModel::class)
            ->join('tenant ON tenant.id = recharge.tenant_id')
            ->where($filter)
            ->field($fields)
            ->order($order)
            ->page($page[0], $page[1])
            ->select();
        return [
            "total" => $total,
            "rows" => $rows
        ];
    }
}
